home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 24 / Amiga Format AFCD24 (Feb 1998, Issue 108).iso / -in_the_mag- / emulation / uae / uae-0.4.3 / cia.c < prev    next >
C/C++ Source or Header  |  1998-01-20  |  15KB  |  688 lines

  1.  /* 
  2.   * UAE - The Un*x Amiga Emulator
  3.   * 
  4.   * CIA chip support
  5.   *
  6.   * Copyright 1995 Bernd Schmidt, Alessandro Bissacco
  7.   * Copyright 1996 Stefan Reinauer
  8.   */
  9.  
  10. #include <stdio.h>
  11. #include <assert.h>
  12. #include <stdlib.h>
  13. #include <time.h>
  14.  
  15. #include "config.h"
  16. #include "amiga.h"
  17. #include "options.h"
  18. #include "events.h"
  19. #include "memory.h"
  20. #include "custom.h"
  21. #include "cia.h"
  22. #include "disk.h"
  23. #include "xwin.h"
  24. #include "keybuf.h"
  25. #include "gui.h"
  26.  
  27. #define DIV10 5 /* Yes, a bad identifier. */
  28.  
  29. /* battclock stuff */
  30. #define RTC_D_ADJ      8
  31. #define RTC_D_IRQ      4
  32. #define RTC_D_BUSY     2
  33. #define RTC_D_HOLD     1
  34. #define RTC_E_t1       8
  35. #define RTC_E_t0       4
  36. #define RTC_E_INTR     2
  37. #define RTC_E_MASK     1
  38. #define RTC_F_TEST     8
  39. #define RTC_F_24_12    4
  40. #define RTC_F_STOP     2
  41. #define RTC_F_RSET     1
  42.  
  43. static UBYTE clock_control_d = RTC_D_ADJ + RTC_D_HOLD;
  44. static UBYTE clock_control_e = 0;
  45. static UBYTE clock_control_f = RTC_F_24_12;
  46.  
  47. static UBYTE ciaaicr,ciaaimask,ciabicr,ciabimask;
  48. static UBYTE ciaacra,ciaacrb,ciabcra,ciabcrb;
  49. static ULONG ciaata,ciaatb,ciabta,ciabtb;
  50. static UWORD ciaala,ciaalb,ciabla,ciablb;
  51. static ULONG ciaatod,ciabtod,ciaatol,ciabtol,ciaaalarm,ciabalarm;
  52. static bool ciaatlatch,ciabtlatch;
  53. static UBYTE ciaapra,ciaaprb,ciaadra,ciaadrb,ciaasdr;
  54. static UBYTE ciabpra,ciabprb,ciabdra,ciabdrb,ciabsdr; 
  55. static int div10;
  56. static int kbstate;
  57. static bool kback;
  58.  
  59. static void setclr(UBYTE *p, UBYTE val)
  60. {
  61.     if (val & 0x80) {
  62.     *p |= val & 0x7F;
  63.     } else {
  64.     *p &= ~val;
  65.     }
  66. }
  67.  
  68. static void RethinkICRA(void)
  69. {
  70.     if (ciaaimask & ciaaicr) {
  71.     ciaaicr |= 0x80;
  72.     custom_bank.wput(0xDFF09C,0x8008);
  73.     } else {
  74.     ciaaicr &= 0x7F;
  75.     custom_bank.wput(0xDFF09C,0x0008);
  76.     }
  77. }
  78.  
  79. static void RethinkICRB(void)
  80. {
  81.     if (ciabimask & ciabicr) {
  82.     ciabicr |= 0x80;
  83.     custom_bank.wput(0xDFF09C,0xA000);
  84.     } else {
  85.     ciabicr &= 0x7F;
  86.     custom_bank.wput(0xDFF09C,0x2000);
  87.     }
  88. }
  89.  
  90. static int lastdiv10;
  91.  
  92. static void CIA_update(void)
  93. {
  94.     unsigned long int ccount = cycles - eventtab[ev_cia].oldcycles + lastdiv10;
  95.     unsigned long int ciaclocks = ccount / DIV10;
  96.  
  97.     int aovfla = 0, aovflb = 0, bovfla = 0, bovflb = 0;
  98.  
  99.     lastdiv10 = div10;
  100.     div10 = ccount % DIV10;
  101.     
  102.     /* CIA A timers */
  103.     if ((ciaacra & 0x21) == 0x01) {
  104.     assert((ciaata+1) >= ciaclocks);
  105.     if ((ciaata+1) == ciaclocks) {
  106.         aovfla = 1;
  107.         if ((ciaacrb & 0x61) == 0x41) {
  108.         if (ciaatb-- == 0) aovflb = 1;        
  109.         }
  110.     }         
  111.     ciaata -= ciaclocks;
  112.     }
  113.     if ((ciaacrb & 0x61) == 0x01) {
  114.     assert((ciaatb+1) >= ciaclocks);
  115.     if ((ciaatb+1) == ciaclocks) aovflb = 1;
  116.     ciaatb -= ciaclocks;
  117.     }
  118.     
  119.     /* CIA B timers */
  120.     if ((ciabcra & 0x21) == 0x01) {
  121.     assert((ciabta+1) >= ciaclocks);
  122.     if ((ciabta+1) == ciaclocks) {
  123.         bovfla = 1;
  124.         if ((ciabcrb & 0x61) == 0x41) {
  125.         if (ciabtb-- == 0) bovflb = 1;
  126.         }
  127.     } 
  128.     ciabta -= ciaclocks;
  129.     }
  130.     if ((ciabcrb & 0x61) == 0x01) {
  131.     assert ((ciabtb+1) >= ciaclocks);
  132.     if ((ciabtb+1) == ciaclocks) bovflb = 1;
  133.     ciabtb -= ciaclocks;
  134.     }
  135.     if (aovfla) {
  136.     ciaaicr |= 1; RethinkICRA();
  137.     ciaata = ciaala;
  138.     if (ciaacra & 0x8) ciaacra &= ~1;
  139.     }
  140.     if (aovflb) {
  141.     ciaaicr |= 2; RethinkICRA();
  142.     ciaatb = ciaalb;
  143.     if (ciaacrb & 0x8) ciaacrb &= ~1;
  144.     }
  145.     if (bovfla) {
  146.     ciabicr |= 1; RethinkICRB();
  147.     ciabta = ciabla;
  148.     if (ciabcra & 0x8) ciabcra &= ~1;
  149.     }
  150.     if (bovflb) {
  151.     ciabicr |= 2; RethinkICRB();
  152.     ciabtb = ciablb;
  153.     if (ciabcrb & 0x8) ciabcrb &= ~1;
  154.     }
  155. }
  156.  
  157. static void CIA_calctimers(void)
  158. {
  159.     int ciaatimea = -1, ciaatimeb = -1, ciabtimea = -1, ciabtimeb = -1;
  160.  
  161.     eventtab[ev_cia].oldcycles = cycles;
  162.     
  163.     if ((ciaacra & 0x21) == 0x01) {
  164.     ciaatimea = (DIV10-div10) + DIV10*ciaata;    
  165.     }
  166.     if ((ciaacrb & 0x61) == 0x41) {
  167.     /* Timer B will not get any pulses if Timer A is off. */
  168.     if (ciaatimea >= 0) {
  169.         /* If Timer A is in one-shot mode, and Timer B needs more than
  170.          * one pulse, it will not underflow. */
  171.         if (ciaatb == 0 || (ciaacra & 0x8) == 0) {
  172.         /* Otherwise, we can determine the time of the underflow. */
  173.         ciaatimeb = ciaatimea + ciaala * DIV10 * ciaatb;
  174.         }
  175.     }
  176.     }
  177.     if ((ciaacrb & 0x61) == 0x01) {
  178.     ciaatimeb = (DIV10-div10) + DIV10*ciaatb;
  179.     }
  180.  
  181.     if ((ciabcra & 0x21) == 0x01) {
  182.     ciabtimea = (DIV10-div10) + DIV10*ciabta;    
  183.     }
  184.     if ((ciabcrb & 0x61) == 0x41) {
  185.     /* Timer B will not get any pulses if Timer A is off. */
  186.     if (ciabtimea >= 0) {
  187.         /* If Timer A is in one-shot mode, and Timer B needs more than
  188.          * one pulse, it will not underflow. */
  189.         if (ciabtb == 0 || (ciabcra & 0x8) == 0) {
  190.         /* Otherwise, we can determine the time of the underflow. */
  191.         ciabtimeb = ciabtimea + ciabla * DIV10 * ciabtb;
  192.         }
  193.     }
  194.     }
  195.     if ((ciabcrb & 0x61) == 0x01) {
  196.     ciabtimeb = (DIV10-div10) + DIV10*ciabtb;
  197.     }
  198.     eventtab[ev_cia].active = (ciaatimea != -1 || ciaatimeb != -1
  199.                    || ciabtimea != -1 || ciabtimeb != -1);
  200.     if (eventtab[ev_cia].active) {
  201.     unsigned long int ciatime = ~0L;
  202.     if (ciaatimea != -1) ciatime = ciaatimea;
  203.     if (ciaatimeb != -1 && ciaatimeb < ciatime) ciatime = ciaatimeb;
  204.     if (ciabtimea != -1 && ciabtimea < ciatime) ciatime = ciabtimea;
  205.     if (ciabtimeb != -1 && ciabtimeb < ciatime) ciatime = ciabtimeb;
  206.     eventtab[ev_cia].evtime = ciatime;
  207.     }
  208.     events_schedule();
  209. }
  210.  
  211. void CIA_handler(void)
  212. {
  213.     CIA_update();
  214.     CIA_calctimers();
  215. }
  216.  
  217. void CIA_hsync_handler(void)
  218. {
  219.     static int keytime = 0;
  220.     
  221.     ciabtod++;
  222.     ciabtod &= 0xFFFFFF;
  223.     if (ciabtod == ciabalarm) {
  224.     ciabicr |= 4; RethinkICRB();
  225.     }
  226.     if (keys_available() && kback && (++keytime & 15) == 0) {
  227.     switch(kbstate) {
  228.      case 0:
  229.         ciaasdr = (BYTE)~0xFB; /* aaarghh... stupid compiler */
  230.         kbstate++;
  231.         break;
  232.      case 1:
  233.         kbstate++;
  234.         ciaasdr = (BYTE)~0xFD;
  235.         break;
  236.      case 2:
  237.         ciaasdr = ~get_next_key();
  238.         break;
  239.     }
  240.     ciaaicr |= 8; RethinkICRA();
  241.     }
  242. }
  243.  
  244. void CIA_vsync_handler()
  245. {    
  246.     ciaatod++;
  247.     ciaatod &= 0xFFFFFF;
  248.     if (ciaatod == ciaaalarm) {
  249.     ciaaicr |= 4; RethinkICRA();
  250.     }
  251. }
  252.  
  253. static UBYTE ReadCIAA(UWORD addr)
  254. {
  255.     UBYTE tmp;
  256.     
  257.     switch(addr & 0xf){
  258.      case 0: 
  259.     tmp = (DISK_status() & 0x3C);
  260.     if (!buttonstate[0]) tmp |= 0x40;
  261.     if (!buttonstate[1]) tmp |= 0x80;
  262.     return tmp;
  263.      case 1:
  264.     return ciaaprb;
  265.      case 2:
  266.     return ciaadra;
  267.      case 3:
  268.     return ciaadrb;
  269.      case 4:
  270.     return ciaata & 0xff;
  271.      case 5:
  272.     return ciaata >> 8;
  273.      case 6:
  274.     return ciaatb & 0xff;
  275.      case 7:
  276.     return ciaatb >> 8;
  277.      case 8:
  278.     if (ciaatlatch) {
  279.         ciaatlatch = 0;
  280.         return ciaatol & 0xff;
  281.     } else return ciaatod & 0xff;
  282.      case 9:
  283.     if (ciaatlatch) return (ciaatol >> 8) & 0xff;
  284.     else return (ciaatod >> 8) & 0xff;
  285.      case 10:
  286.     ciaatlatch = 1; ciaatol = ciaatod; /* ??? only if not already latched? */
  287.     return (ciaatol >> 16) & 0xff;
  288.      case 12:
  289.     return ciaasdr;
  290.      case 13:
  291.     tmp = ciaaicr; ciaaicr = 0; RethinkICRA(); return tmp;
  292.      case 14:
  293.     return ciaacra;
  294.      case 15:
  295.     return ciaacrb;
  296.     }
  297.     return 0;
  298. }
  299.  
  300. static UBYTE ReadCIAB(UWORD addr)
  301. {
  302.     UBYTE tmp;
  303.     
  304.     switch(addr & 0xf){
  305.      case 0: 
  306.     return ciabpra;
  307.      case 1:
  308.     return ciabprb;
  309.      case 2:
  310.     return ciabdra;
  311.      case 3:
  312.     return ciabdrb;
  313.      case 4:
  314.     return ciabta & 0xff;
  315.      case 5:
  316.     return ciabta >> 8;
  317.      case 6:
  318.     return ciabtb & 0xff;
  319.      case 7:
  320.     return ciabtb >> 8;
  321.      case 8:
  322.     if (ciabtlatch) {
  323.         ciabtlatch = 0;
  324.         return ciabtol & 0xff;
  325.     } else return ciabtod & 0xff;
  326.      case 9:
  327.     if (ciabtlatch) return (ciabtol >> 8) & 0xff;
  328.     else return (ciabtod >> 8) & 0xff;
  329.      case 10:
  330.     ciabtlatch = 1; ciabtol = ciabtod;
  331.     return (ciabtol >> 16) & 0xff;
  332.      case 12:
  333.     return ciabsdr;
  334.      case 13:
  335.     tmp = ciabicr; ciabicr = 0; RethinkICRB();
  336.     if (dskdmaen != 2)
  337.         if (indexpulse == 0){
  338.         tmp |= 0x10;
  339.         DISK_Index();
  340.         indexpulse = 100; /* whatever */
  341.         } else {
  342.         indexpulse--;
  343.         }        
  344.     return tmp;
  345.      case 14:
  346.     return ciabcra;
  347.      case 15:
  348.     return ciabcrb;
  349.     }
  350.     return 0;
  351. }
  352.  
  353. static void WriteCIAA(UWORD addr,UBYTE val)
  354. {
  355.     switch(addr & 0xf){
  356.      case 0: 
  357.     ciaapra = (ciaapra & ~0x3) | (val & 0x3); LED(ciaapra & 0x2);
  358.     gui_led (0, !(ciaapra & 2));
  359.     break;
  360.      case 1:
  361.     ciaaprb = val; break;
  362.      case 2:
  363.     ciaadra = val; break;
  364.      case 3:
  365.     ciaadrb = val; break;
  366.      case 4:
  367.     CIA_update();
  368.     ciaala = (ciaala & 0xff00) | val;
  369.     CIA_calctimers();
  370.     break;
  371.      case 5:
  372.     CIA_update();
  373.     ciaala = (ciaala & 0xff) | (val << 8);
  374.     if ((ciaacra & 1) == 0) {
  375.         ciaata = ciaala;
  376.     }
  377.     if (ciaacra & 8) { 
  378.         ciaata = ciaala; 
  379.         ciaacra |= 1; 
  380.     }/*??? load latch always? */
  381.     CIA_calctimers();
  382.     break;
  383.      case 6:
  384.     CIA_update();
  385.     ciaalb = (ciaalb & 0xff00) | val;
  386.     CIA_calctimers();
  387.     break;
  388.      case 7:
  389.     CIA_update();
  390.     ciaalb = (ciaalb & 0xff) | (val << 8);
  391.     if ((ciaacrb & 1) == 0) ciaatb = ciaalb;
  392.     if (ciaacrb & 8) { ciaatb = ciaalb; ciaacrb |= 1; }
  393.     CIA_calctimers();
  394.     break;
  395.      case 8:
  396.     if (ciaacrb & 0x80){
  397.         ciaaalarm = (ciaaalarm & ~0xff) | val;
  398.     } else {
  399.         ciaatod = (ciaatod & ~0xff) | val;
  400.     }
  401.     break;
  402.      case 9:
  403.     if (ciaacrb & 0x80){
  404.         ciaaalarm = (ciaaalarm & ~0xff00) | (val << 8);
  405.     } else {
  406.         ciaatod = (ciaatod & ~0xff00) | (val << 8);
  407.     }
  408.     break;
  409.      case 10:
  410.     if (ciaacrb & 0x80){
  411.         ciaaalarm = (ciaaalarm & ~0xff0000) | (val << 16);
  412.     } else {
  413.         ciaatod = (ciaatod & ~0xff0000) | (val << 16);
  414.     }
  415.     break;
  416.      case 12:
  417.     ciaasdr = val; break;
  418.      case 13:
  419.     setclr(&ciaaimask,val); break; /* ??? call RethinkICR() ? */
  420.      case 14:
  421.     CIA_update();
  422.     ciaacra = val;
  423.     if (ciaacra & 0x10){
  424.         ciaacra &= ~0x10;
  425.         ciaata = ciaala;
  426.     }
  427.     if (ciaacra & 0x40) {
  428.         kback = true;
  429.     }
  430.     CIA_calctimers();
  431.     break;
  432.      case 15:
  433.     CIA_update();
  434.     ciaacrb = val; 
  435.     if (ciaacrb & 0x10){
  436.         ciaacrb &= ~0x10;
  437.         ciaatb = ciaalb;
  438.     }
  439.     CIA_calctimers();
  440.     break;
  441.     }
  442. }
  443.  
  444. static void WriteCIAB(UWORD addr,UBYTE val)
  445. {
  446.     switch(addr & 0xf){
  447.      case 0:
  448.     ciabpra = (ciabpra & ~0x3) | (val & 0x3); break;
  449.      case 1:
  450.     ciabprb = val; DISK_select(val); break;
  451.      case 2:
  452.     ciabdra = val; break;
  453.      case 3:
  454.     ciabdrb = val; break;
  455.      case 4:
  456.     CIA_update();
  457.     ciabla = (ciabla & 0xff00) | val;
  458.     CIA_calctimers();
  459.     break;
  460.      case 5:
  461.     CIA_update();
  462.     ciabla = (ciabla & 0xff) | (val << 8);
  463.     if ((ciabcra & 1) == 0) ciabta = ciabla;
  464.     if (ciabcra & 8) { ciabta = ciabla; ciabcra |= 1; } 
  465.     CIA_calctimers();
  466.     break;
  467.      case 6:
  468.     CIA_update();
  469.     ciablb = (ciablb & 0xff00) | val;
  470.     CIA_calctimers();
  471.     break;
  472.      case 7:
  473.     CIA_update();
  474.     ciablb = (ciablb & 0xff) | (val << 8);
  475.     if ((ciabcrb & 1) == 0) ciabtb = ciablb;
  476.     if (ciabcrb & 8) { ciabtb = ciablb; ciabcrb |= 1; }
  477.     CIA_calctimers();
  478.     break;
  479.      case 8:
  480.     if (ciabcrb & 0x80){
  481.         ciabalarm = (ciabalarm & ~0xff) | val;
  482.     } else {
  483.         ciabtod = (ciabtod & ~0xff) | val;
  484.     }
  485.     break;
  486.      case 9:
  487.     if (ciabcrb & 0x80){
  488.         ciabalarm = (ciabalarm & ~0xff00) | (val << 8);
  489.     } else {
  490.         ciabtod = (ciabtod & ~0xff00) | (val << 8);
  491.     }
  492.     break;
  493.      case 10:
  494.     if (ciabcrb & 0x80){
  495.         ciabalarm = (ciabalarm & ~0xff0000) | (val << 16);
  496.     } else {
  497.         ciabtod = (ciabtod & ~0xff0000) | (val << 16);
  498.     }
  499.     break;
  500.      case 12:
  501.     ciabsdr = val; 
  502.     break;
  503.      case 13:
  504.     setclr(&ciabimask,val); 
  505.     break;
  506.      case 14:
  507.     CIA_update();
  508.     ciabcra = val;
  509.     if (ciabcra & 0x10){
  510.         ciabcra &= ~0x10;
  511.         ciabta = ciabla;
  512.     }
  513.     CIA_calctimers();
  514.     break;
  515.      case 15:
  516.     CIA_update();
  517.     ciabcrb = val; 
  518.     if (ciabcrb & 0x10){
  519.         ciabcrb &= ~0x10;
  520.         ciabtb = ciablb;
  521.     }
  522.     CIA_calctimers();
  523.     break;
  524.     }
  525. }
  526.  
  527. void CIA_reset(void)
  528. {
  529.     kback = true;
  530.     kbstate = 0;
  531.     
  532.     ciaatlatch = ciabtlatch = 0;
  533.     ciaatod = ciabtod = 0;
  534.     ciaaicr = ciabicr = ciaaimask = ciabimask = 0;
  535.     ciaacra = ciaacrb = ciabcra = ciabcrb = 0x4; /* outmode = toggle; */
  536.     div10 = 0;
  537.     lastdiv10 = 0;
  538.     CIA_calctimers();
  539. }
  540.  
  541. void dumpcia(void)
  542. {
  543.     printf("A: CRA: %02x, CRB: %02x, IMASK: %02x, TOD: %08lx %7s TA: %04lx, TB: %04lx\n",
  544.        (int)ciaacra, (int)ciaacrb, (int)ciaaimask, ciaatod, 
  545.        ciaatlatch ? " latched" : "", ciaata, ciaatb);
  546.     printf("B: CRA: %02x, CRB: %02x, IMASK: %02x, TOD: %08lx %7s TA: %04lx, TB: %04lx\n",
  547.        (int)ciabcra, (int)ciabcrb, (int)ciabimask, ciabtod, 
  548.        ciabtlatch ? " latched" : "", ciabta, ciabtb);
  549. }
  550.  
  551. /* CIA memory access */
  552.  
  553. static ULONG cia_lget(CPTR) REGPARAM;
  554. static UWORD cia_wget(CPTR) REGPARAM;
  555. static UBYTE cia_bget(CPTR) REGPARAM;
  556. static void  cia_lput(CPTR, ULONG) REGPARAM;
  557. static void  cia_wput(CPTR, UWORD) REGPARAM;
  558. static void  cia_bput(CPTR, UBYTE) REGPARAM;
  559.  
  560. addrbank cia_bank = {
  561.     cia_lget, cia_wget, cia_bget,
  562.     cia_lput, cia_wput, cia_bput,
  563.     default_xlate, default_check
  564. };
  565.  
  566. ULONG cia_lget(CPTR addr)
  567. {
  568.     return cia_bget(addr+3);
  569. }
  570.  
  571. UWORD cia_wget(CPTR addr)
  572. {
  573.     return cia_bget(addr+1);
  574. }
  575.  
  576. UBYTE cia_bget(CPTR addr)
  577. {
  578. #ifdef DUALCPU
  579.     customacc = true;
  580. #endif
  581.     if ((addr & 0xF0FF) == 0xE001)
  582.         return ReadCIAA((addr & 0xF00) >> 8);
  583.     if ((addr & 0xF0FF) == 0xD000)
  584.         return ReadCIAB((addr & 0xF00) >> 8);
  585.     return 0;
  586. }
  587.  
  588. void cia_lput(CPTR addr, ULONG value)
  589. {
  590.     cia_bput(addr+3,value); /* FIXME ? */
  591. }
  592.  
  593. void cia_wput(CPTR addr, UWORD value)
  594. {
  595.     cia_bput(addr+1,value);
  596. }
  597.  
  598. void cia_bput(CPTR addr, UBYTE value)
  599. {
  600. #ifdef DUALCPU
  601.     customacc = true;
  602. #endif
  603.     if ((addr & 0xF0FF) == 0xE001)
  604.         WriteCIAA((addr & 0xF00) >> 8,value);
  605.     if ((addr & 0xF0FF) == 0xD000)
  606.         WriteCIAB((addr & 0xF00) >> 8,value);
  607. }
  608.  
  609. /* battclock memory access */
  610.  
  611. static ULONG clock_lget(CPTR) REGPARAM;
  612. static UWORD clock_wget(CPTR) REGPARAM;
  613. static UBYTE clock_bget(CPTR) REGPARAM;
  614. static void  clock_lput(CPTR, ULONG) REGPARAM;
  615. static void  clock_wput(CPTR, UWORD) REGPARAM;
  616. static void  clock_bput(CPTR, UBYTE) REGPARAM;
  617.  
  618. addrbank clock_bank = {
  619.     clock_lget, clock_wget, clock_bget,
  620.     clock_lput, clock_wput, clock_bput,
  621.     default_xlate, default_check
  622. };
  623.  
  624. ULONG clock_lget(CPTR addr)
  625. {
  626.     return clock_bget(addr+3);
  627. }
  628.  
  629. UWORD clock_wget(CPTR addr)
  630. {
  631.     return clock_bget(addr+1);
  632. }
  633.  
  634. UBYTE clock_bget(CPTR addr)
  635. {
  636. #ifdef DUALCPU
  637.     customacc = true;
  638. #endif
  639.     
  640.     time_t t=time(0);
  641.     struct tm *ct;
  642.     ct=localtime(&t);
  643.     switch (addr & 0x3f)
  644.     {
  645.      case 0x03: return ct->tm_sec % 10;
  646.      case 0x07: return ct->tm_sec / 10;
  647.      case 0x0b: return ct->tm_min % 10;
  648.      case 0x0f: return ct->tm_min / 10;
  649.      case 0x13: return ct->tm_hour % 10;
  650.      case 0x17: return ct->tm_hour / 10;
  651.      case 0x1b: return ct->tm_mday % 10;
  652.      case 0x1f: return ct->tm_mday / 10;
  653.      case 0x23: return (ct->tm_mon+1) % 10;
  654.      case 0x27: return (ct->tm_mon+1) / 10;
  655.      case 0x2b: return ct->tm_year % 10;
  656.      case 0x2f: return ct->tm_year / 10;
  657. #if 1
  658.      case 0x33: return ct->tm_wday;  /*Hack by -=SR=- */
  659.      case 0x37: return clock_control_d;
  660.      case 0x3b: return clock_control_e;
  661.      case 0x3f: return clock_control_f;
  662. #endif
  663.     }
  664.     return 0;
  665. }
  666.  
  667. void clock_lput(CPTR addr, ULONG value)
  668. {
  669.     /* No way */
  670. }
  671.  
  672. void clock_wput(CPTR addr, UWORD value)
  673. {
  674.     /* No way */
  675. }
  676.  
  677. void clock_bput(CPTR addr, UBYTE value)
  678. {
  679.     switch (addr & 0x3f)
  680.     {
  681. #if 1
  682.      case 0x37: clock_control_d=value; break;
  683.      case 0x3b: clock_control_e=value; break;
  684.      case 0x3f: clock_control_f=value; break;
  685. #endif
  686.     }
  687. }
  688.